package mincostmaxflow;

import com.mxgraph.layout.hierarchical.mxHierarchicalLayout;
import com.mxgraph.model.mxCell;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxConstants;
import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxStylesheet;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.File;
import java.util.Hashtable;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;


/**
 *
 * @author Anatolijs.Mozgovs
 */
public class MinCostGUI extends javax.swing.JFrame implements GraphDisplayable, Observer {

    /**
     * a CSV file containig data about {@link Graph Graph}.
     */
    private File file = null;

    /**
     * an instance of the {@link Graph Graph} class.
     */
    private Graph graph = null;

    /**
     * an instance of the {@link MinCostMaxFlow MinCostMaxFlow} class. used to
     */
    private MinCostMaxFlow mcmf = null;
    public MinCostGUI() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jFileChooser1 = new javax.swing.JFileChooser();
        jScrollPane1 = new javax.swing.JScrollPane();
        showOverallFlowArea = new javax.swing.JTextArea();
        jScrollPane2 = new javax.swing.JScrollPane();
        showStepFlowArea = new javax.swing.JTextArea();
        overallFlowLabel = new javax.swing.JLabel();
        labelCurrentStepFlow = new javax.swing.JLabel();
        panelShowGraph = new javax.swing.JPanel();
        labelGraphShow = new javax.swing.JLabel();
        tabbedPaneSteps = new javax.swing.JTabbedPane();
        jToolBarMain = new javax.swing.JToolBar();
        openFileButton = new javax.swing.JButton();
        startButton = new javax.swing.JButton();
        jMenuBarMain = new javax.swing.JMenuBar();
        jMenuFile = new javax.swing.JMenu();
        jMenuItemOpenFile = new javax.swing.JMenuItem();
        jMenuItemRun = new javax.swing.JMenuItem();
        jMenuHelp = new javax.swing.JMenu();
        jMenuItemHelp = new javax.swing.JMenuItem();
        jMenuItemAbout = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Shortest path Calculation");
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));

        showOverallFlowArea.setColumns(20);
        showOverallFlowArea.setRows(5);
        jScrollPane1.setViewportView(showOverallFlowArea);

        showStepFlowArea.setColumns(20);
        showStepFlowArea.setRows(5);
        jScrollPane2.setViewportView(showStepFlowArea);

        overallFlowLabel.setText("Overall Flow");

        labelCurrentStepFlow.setText("Current Flow Path");

        panelShowGraph.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
        panelShowGraph.setMaximumSize(new java.awt.Dimension(400, 32767));
        panelShowGraph.setLayout(new java.awt.GridLayout(1, 0));

        labelGraphShow.setText("Initial Graph");

        jToolBarMain.setFloatable(false);
        jToolBarMain.setRollover(true);

        openFileButton.setText("Open file..");
        openFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openFileButtonActionPerformed(evt);
            }
        });
        jToolBarMain.add(openFileButton);

        startButton.setText("Run");
        startButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startButtonActionPerformed(evt);
            }
        });
        jToolBarMain.add(startButton);

        jMenuFile.setText("File");

        jMenuItemOpenFile.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItemOpenFile.setText("Open File..");
        jMenuItemOpenFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemOpenFileActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItemOpenFile);

        jMenuItemRun.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItemRun.setText("Run..");
        jMenuItemRun.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemRunActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItemRun);

        jMenuBarMain.add(jMenuFile);

        jMenuHelp.setText("Help");

        jMenuItemHelp.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F1, 0));
        jMenuItemHelp.setText("Help");
        jMenuItemHelp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemHelpActionPerformed(evt);
            }
        });
        jMenuHelp.add(jMenuItemHelp);

        jMenuItemAbout.setText("About");
        jMenuItemAbout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemAboutActionPerformed(evt);
            }
        });
        jMenuHelp.add(jMenuItemAbout);

        jMenuBarMain.add(jMenuHelp);

        setJMenuBar(jMenuBarMain);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBarMain, javax.swing.GroupLayout.DEFAULT_SIZE, 657, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(tabbedPaneSteps, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 637, Short.MAX_VALUE)
                    .addComponent(panelShowGraph, javax.swing.GroupLayout.DEFAULT_SIZE, 637, Short.MAX_VALUE)
                    .addComponent(labelGraphShow)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(labelCurrentStepFlow)
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 254, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(16, 16, 16)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(layout.createSequentialGroup()
                                .addGap(113, 113, 113)
                                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE))
                            .addComponent(overallFlowLabel))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jToolBarMain, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(overallFlowLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(labelCurrentStepFlow)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(labelGraphShow)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(panelShowGraph, javax.swing.GroupLayout.PREFERRED_SIZE, 195, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(tabbedPaneSteps, javax.swing.GroupLayout.DEFAULT_SIZE, 273, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void openFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openFileButtonActionPerformed
        jFileChooser1.setCurrentDirectory(new File ("."));
        int returnVal = jFileChooser1.showOpenDialog(MinCostGUI.this);
        if(returnVal == JFileChooser.APPROVE_OPTION){
            try {
                file = jFileChooser1.getSelectedFile();
                graph = GraphFileParser.readFile(file.getCanonicalPath());

		//TODO: make this not the only option using a chooseActionComboBox
		mcmf = new MinCostMaxFlow(graph);

		mcmf.addObserver(this);
		panelShowGraph.setLayout(new BorderLayout(5, 5));
		showGraphFancy(graph, panelShowGraph, true);
            } catch (Exception ex) {
		JOptionPane.showMessageDialog(this, ex.getMessage(), "Exception", JOptionPane.ERROR_MESSAGE);
                Logger.getLogger(MinCostGUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_openFileButtonActionPerformed

    private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed
        if(file != null){
            try {
		// starts the event thread
		Thread thread = new Thread(mcmf);
		thread.start();
            }
            catch (Exception ex) {
		JOptionPane.showMessageDialog(this, ex.getMessage());
                Logger.getLogger(MinCostGUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
	else
	    JOptionPane.showMessageDialog(this, "You should open a file first",
		    "Error", JOptionPane.ERROR_MESSAGE);
    }//GEN-LAST:event_startButtonActionPerformed

    private void jMenuItemHelpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemHelpActionPerformed

	String helpMessage = "To use this program at this state you should " +
		"have a properly composed graph file with a flow network inside. " +
		"\nA properly composed graph file is a simple CSV file, where each line " +
		"contains information about one edge of the graph. First two values are " +
		"\nedge's starting and ending vertices respectively. Then edge's cost per " +
		"one item and the edge's capacity." +
		"\nBesides, the file must contain information about network's source(s) and " +
		"drain(s). \nTo specify sources, line of file should start with 'Source' " +
		"(no quotes), then comma, and then source vertices, comma separated." +
		"\nSame with drains, only keyword 'Drain' should be used." +
		"\n\nExample:" +
		"\nSource, 1" +
		"\nDrain, 8" +
		"\n1,\t2,\t31,\t1" +
		"\n1,\t3,\t4,\t10" +
		"\n2,\t4,\t31,\t1" +
		"\n3,\t4,\t1,\t10" +
		"\n3,\t7,\t30,\t10" +
		"\n4,\t5,\t10,\t10" +
		"\n5,\t6,\t31,\t1" +
		"\n5,\t7,\t1,\t10" +
		"\n6,\t8,\t31,\t1" +
		"\n7,\t8,\t4,\t10" +
		"\n\nYou can copy this example data to a file, and then open it from the program.";

	JTextPane textPaneHelp = new JTextPane();
	textPaneHelp.setText(helpMessage);
	
/*
	JTextArea textAreaHelp = new JTextArea(helpMessage);
	textAreaHelp.setEditable(false);
*/
//	JScrollPane scrollPaneHelp = new JScrollPane(textAreaHelp);

	JOptionPane.showMessageDialog(this, textPaneHelp, "Help contents", JOptionPane.PLAIN_MESSAGE);

//	JOptionPane.showMessageDialog(this, "To use this program at this state you should " +
//		"have a properly composed graph file with a flow network inside. " +
//		"\nA properly composed graph file is a simple CSV file, where each line " +
//		"contains information about one edge of the graph. First two values are " +
//		"\nedge's starting and ending vertices respectively. Then edge's cost per " +
//		"one item and the edge's capacity." +
//		"\nBesides, the file must contain information about network's source(s) and" +
//		"drain(s). \nTo specify sources, line of file should start with 'Source'" +
//		" (no quotes), then comma, and then source vertices, comma separated." +
//		"\nSame with drains, only keyword 'Drain' should be used." +
//		"\n\nExample:" +
//		"\nSource, 1" +
//		"\nDrain, 8" +
//		"\n1,\t2,\t31,\t1" +
//		"\n1,\t3,\t4,\t10" +
//		"\n2,\t4,\t31,\t1" +
//		"\n3,\t4,\t1,\t10" +
//		"\n3,\t7,\t30,\t10" +
//		"\n4,\t5,\t10,\t10" +
//		"\n5,\t6,\t31,\t1" +
//		"\n5,\t7,\t1,\t10" +
//		"\n6,\t8,\t31,\t1" +
//		"\n7,\t8,\t4,\t10");

    }//GEN-LAST:event_jMenuItemHelpActionPerformed

    private void jMenuItemRunActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemRunActionPerformed

	startButtonActionPerformed(evt);

    }//GEN-LAST:event_jMenuItemRunActionPerformed

    private void jMenuItemAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemAboutActionPerformed

	String aboutMessage = "GraphWorks ver 0.6\n" +
		"Author: Anatolijs Mozgovs\n" +
		"Libraries used:\n" +
		"*  OstermillerUtils (http://ostermiller.org/utils/) to deal with CSV files.\n" +
		"*  JGraphX (http://www.jgraph.com/jgraphx.html) to visualize graphs.";

	JOptionPane.showMessageDialog(this, aboutMessage, "About..", JOptionPane.PLAIN_MESSAGE);

    }//GEN-LAST:event_jMenuItemAboutActionPerformed

    private void jMenuItemOpenFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemOpenFileActionPerformed
	openFileButtonActionPerformed(evt);
    }//GEN-LAST:event_jMenuItemOpenFileActionPerformed

    /**
    * @param args the command line arguments
    */
    public static void main(String args[])  {
	try {
	    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
	} catch (Exception ex) {
	    JOptionPane.showMessageDialog(null, ex.getMessage(),"Exception", JOptionPane.ERROR_MESSAGE);
	    Logger.getLogger(MinCostGUI.class.getName()).log(Level.SEVERE, null, ex);
	}
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MinCostGUI().setVisible(true);
            }
        });
    }

    /**shows graph textually*/
    public void showGraph(String graph_contents, boolean isOverall){
        if(isOverall){
            showOverallFlowArea.append(graph_contents);
        }
        else{
            showStepFlowArea.append(graph_contents);
        }
    }
    
    /**shows graph textually*/
    public void showGraph(Route<Edge> r){
	for(Edge e : r){
	    showStepFlowArea.append(e.toString());
	    showStepFlowArea.append(System.getProperty("line.separator"));
	}
	showStepFlowArea.append(System.getProperty("line.separator"));
    }

    /**shows graph textually*/
    public void showGraph(Graph<Edge> g){
	for(Edge e : g){
	    showOverallFlowArea.append(e.toString());
	    showOverallFlowArea.append(System.getProperty("line.separator"));
	}
	showOverallFlowArea.append(System.getProperty("line.separator"));
    }

//    JPanel tab;
    JSplitPane tab;
    int tab_amount = 1;
    public void update(Observable obj, Object arg){
	JPanel route;
	JPanel flowGraph;
	if (arg instanceof Graph){
	    showGraph((Graph<Edge>)arg);

	    flowGraph = makeNewPanel("current flowgraph", false);
	    showGraphFancy((Graph<Edge>)arg, flowGraph, true);
//	    tab.add(flowGraph);
	    tab.setBottomComponent(flowGraph);
	    tab.revalidate();
	    tab.repaint();
	}
	else if (arg instanceof Route){
	    showGraph((Route<Edge>) arg);

	    tab = addTab(String.valueOf(tab_amount++));
	    route = makeNewPanel("current route", false);

	    showGraphFancy((Route<Edge>) arg, route, true);

//	    tab.add(route);
	    tab.setTopComponent(route);
//	    tab.revalidate();
//	    tab.repaint();

	}
    }

    /**
     * Creates, adds and returns a new {@link javax.swing.JSplitPane JSplitPane} as a tab. 
     * @param text tooltip text
     * @return JSplitPane
     */
    private JSplitPane addTab(String text){
//    private JPanel addTab(String text){
//	JPanel stepTab;
//	stepTab = makeNewPanel(text, true);

	JSplitPane stepTab = makeNewSplitPane();

	tabbedPaneSteps.addTab("Step " + text, null, stepTab, "Step " + text);
//	tabbedPaneSteps.revalidate();
//	tabbedPaneSteps.repaint();

	return stepTab;
    }

    private JSplitPane makeNewSplitPane(){
	JSplitPane splitPane;
	splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, false);

	splitPane.setDividerLocation(50);

	return splitPane;
    }

    /**
     * creates and returns a new {@link JPanel JPanel} to be used as a tab with a name
     * specified
     * @param text name for a tab pane
     * @return
     */
    protected JPanel makeNewPanel(String text, boolean isTab) {
	JPanel panel;
	if(isTab){
	    panel = new JPanel(new GridLayout(2, 1));
	}
	else{
	    panel = new JPanel(new GridLayout(1,1));
	}
	panel.setPreferredSize(new Dimension(500, 500));
//	JLabel filler = new JLabel(text);
//	filler.setHorizontalAlignment(JLabel.CENTER);
//	panel.setLayout(new GridLayout(1, 1));
//	panel.add(filler);
	return panel;
    }

    /**
     * returns true if a vertex with specified <b>value</b> exists in mxGraph
     * @param value an <code>int</code> containing the value to search for
     * @param graph an instance of the {@link mxGraph mxGraph} in which to perform search
     * @return <code>true</code> if vertex exists, <code>false</code> otherwise.
     */
    private boolean vertexExists(int value, mxGraph graph){
	Object[] vertices = graph.getChildVertices(graph.getDefaultParent());
	for(Object o : vertices){
	    if(o instanceof mxCell){
		mxCell cell = (mxCell)o;
		if(cell.isVertex() &&
			cell.getValue().toString().equalsIgnoreCase(Integer.toString(value))){
		    return true;
		}
	    }
	}
	return false;
    }

    /**
     * returns a Vertex from the graph based on <b>value</b> given. assumes that value of
     * each vertex is unique.
     * @param value an <code>int</code> containing the value to search for
     * @param graph an instance of the {@link mxGraph mxGraph} in which to perform search
     * @return mxCell or null if nothing found
     */
    private mxCell getVertex(int value, mxGraph graph){
	Object[] vertices = graph.getChildVertices(graph.getDefaultParent());
	for(Object o : vertices){
	    if(o instanceof mxCell){
		mxCell cell = (mxCell)o;
		if(cell.isVertex() &&
			cell.getValue().toString().equalsIgnoreCase(Integer.toString(value))){
		    return cell;
		}
	    }
	}
	return null;
    }

    /**
     * testing function which displays a graph nicely
     * @param g an instance of the {@link Graph Graph} class
     */
//    public void showGraphFancy(Route<Edge> g, JPanel location){
    public void showGraphFancy(Route<Edge> g, JPanel location, boolean doLayouting){
	mxGraph fancyGraph = new mxGraph();
	Object parent = fancyGraph.getDefaultParent();

	int initialX = 20;
	int initialY = 20;

	fancyGraph.getModel().beginUpdate();
	try{

//	    setGraphStyle(fancyGraph);


	    fancyGraph.setCellsMovable(false);
	    fancyGraph.setCellsResizable(false);
	    fancyGraph.setCellsBendable(false);
	    fancyGraph.setCellsCloneable(false);
	    fancyGraph.setCellsDeletable(false);
	    fancyGraph.setCellsDisconnectable(false);
	    fancyGraph.setCellsEditable(false);
	    fancyGraph.setEdgeLabelsMovable(false);
	    fancyGraph.setVertexLabelsMovable(false);
	    fancyGraph.setAllowDanglingEdges(false);
	    fancyGraph.setCellsLocked(true);
	    fancyGraph.setEnabled(false);


	    for(Edge e : g){
		Object src;
		Object drn;
		if(!(vertexExists(e.source, fancyGraph))){
		    src = fancyGraph.insertVertex(parent, null, 
			    String.valueOf(e.source), initialX, initialY, 20, 20);
		    initialY+=40;
		}
		else{
		    src = getVertex(e.source, fancyGraph);
		}

		if(!(vertexExists(e.destination, fancyGraph))){
		    drn = fancyGraph.insertVertex(parent, null, 
			    String.valueOf(e.destination), initialX, initialY, 20, 20);
		    initialY+=40;
		}
		else{
		    drn = getVertex(e.destination, fancyGraph);
		}

//		fancyGraph.insertEdge(parent, null,
//			"<table border=\"1\"><tr><td>"+String.valueOf(e.cost) + " : " + String.valueOf(e.capacity_or_flow)+"</td></tr></table>",
//			src, drn);
		fancyGraph.insertEdge(parent, null,
			String.valueOf(e.cost) + " : " + String.valueOf(e.capacity_or_flow),
			src, drn);
	    }
	    
	    /**almost bullshit*/
//	    new mxStackLayout(fancyGraph, true).execute(parent);
	    /**bullshit*/
//	    new mxParallelEdgeLayout(fancyGraph, 25).execute(parent);
	    /**almost bullshit*/
//	    mxFastOrganicLayout FOL = new mxFastOrganicLayout(fancyGraph);
//	    FOL.execute(parent);
	    /**works exactly as advertised, produces a circle. useless then*/
//	    mxCircleLayout mxCL = new mxCircleLayout(fancyGraph, 170);
//	    mxCL.execute(parent);
	    /**doesn't work, throws a NullPointerException*/
//	    mxOrganicLayout OL = new mxOrganicLayout(fancyGraph);
//	    OL.setFineTuning(true);
//	    OL.setOptimizeEdgeCrossing(true);
//	    OL.execute(parent);
	    /**bullshit*/
//	    new mxOrthogonalLayout(fancyGraph).execute(parent);
	    /**good, mostly*/
//	    mxCompactTreeLayout mxCT = new mxCompactTreeLayout(fancyGraph, false);
//	    mxCT.setMoveTree(true);
//	    mxCT.setLevelDistance(30);
//	    mxCT.setNodeDistance(40);
//	    mxCT.execute(parent);

	    if(doLayouting){
		/**best, by far*/
		mxHierarchicalLayout HL =
			new mxHierarchicalLayout(fancyGraph, SwingConstants.WEST);
		HL.execute(parent);
	    }
	    /**bullshit*/
//	    mxPartitionLayout PL = new mxPartitionLayout(fancyGraph, false, 40);
//	    PL.execute(parent);

	    
	}
	catch(Exception ex){
	    JOptionPane.showMessageDialog(this, ex.toString());
	}
	finally{
	    fancyGraph.getModel().endUpdate();
	}


	mxGraphComponent gComponent = new mxGraphComponent(fancyGraph);
	gComponent.setBorder(BorderFactory.createLineBorder(Color.BLACK));
//	gComponent.setPreferredSize(new Dimension(50, 20));

	location.add(gComponent);

	location.revalidate();
	location.repaint();
//	panelShowGraph.add(gComponent);
//	panelShowGraph.revalidate();
//	panelShowGraph.repaint();
    }

    private void setGraphStyle(mxGraph mxG){
	mxStylesheet stylesheet = mxG.getStylesheet();
	Hashtable<String, Object> style = new Hashtable<String, Object>();
	style.put(mxConstants.STYLE_FONTCOLOR, "red");
	style.put(mxConstants.STYLE_FONTSIZE, 14);
	style.put(mxConstants.STYLE_ENDARROW, mxConstants.ARROW_CLASSIC);
	stylesheet.putCellStyle("MYSTYLE", style);
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JFileChooser jFileChooser1;
    private javax.swing.JMenuBar jMenuBarMain;
    private javax.swing.JMenu jMenuFile;
    private javax.swing.JMenu jMenuHelp;
    private javax.swing.JMenuItem jMenuItemAbout;
    private javax.swing.JMenuItem jMenuItemHelp;
    private javax.swing.JMenuItem jMenuItemOpenFile;
    private javax.swing.JMenuItem jMenuItemRun;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JToolBar jToolBarMain;
    private javax.swing.JLabel labelCurrentStepFlow;
    private javax.swing.JLabel labelGraphShow;
    private javax.swing.JButton openFileButton;
    private javax.swing.JLabel overallFlowLabel;
    private javax.swing.JPanel panelShowGraph;
    private javax.swing.JTextArea showOverallFlowArea;
    private javax.swing.JTextArea showStepFlowArea;
    private javax.swing.JButton startButton;
    private javax.swing.JTabbedPane tabbedPaneSteps;
    // End of variables declaration//GEN-END:variables
}
